package com.qmul.testapp;

import java.io.FileOutputStream;

import java.io.IOException;
import java.util.ArrayList;

import android.app.Dialog;
import android.app.PendingIntent;

import android.content.Intent;
import android.content.IntentSender.SendIntentException;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.location.Geocoder;
import android.location.Location;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;


import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesClient;
import com.google.android.gms.common.GooglePlayServicesClient.OnConnectionFailedListener;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.location.ActivityRecognitionClient;
import com.google.android.gms.location.LocationClient;
import com.google.android.gms.maps.CameraUpdate;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.SnapshotReadyCallback;
import com.google.android.gms.maps.GoogleMap.OnCameraChangeListener;
import com.google.android.gms.maps.GoogleMap.OnMapLongClickListener;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.GoogleMap.OnMarkerClickListener;
import com.google.android.gms.maps.GoogleMap.OnMyLocationChangeListener;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.Circle;
import com.google.android.gms.maps.model.CircleOptions;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.maps.model.PolygonOptions;
import com.google.android.gms.maps.model.Polyline;
import com.google.android.gms.maps.model.PolylineOptions;

import java.util.List;
import java.util.Locale;

import android.annotation.SuppressLint;

import android.database.sqlite.SQLiteDatabase;

import android.location.Address;


public class MainActivity extends FragmentActivity implements
GooglePlayServicesClient.ConnectionCallbacks,
OnConnectionFailedListener,
OnMyLocationChangeListener, OnMarkerClickListener, OnMapLongClickListener, OnClickListener, OnCameraChangeListener{

	private GoogleMap map;
	public LocationClient mLocationClient;
	public Location myLocation;
	public Geocoder geo;
	public float zoomLevel = (float) 16;
	public ArrayList<LatLng> storeMarkerLocs = new ArrayList<LatLng>();
	public boolean sLine = false;
    public Button addMarker;
    public Circle circle;
    public CircleOptions myZone;
    public int camPics = 0;
    public double longitude;
    public double latitude;
    
    
    // User Activity (Movement) Recognition
    // Constants that define the activity detection interval
    public static final int MILLISECONDS_PER_SECOND = 1000;
    public static final int DETECTION_INTERVAL_SECONDS = 20;
    public static final int DETECTION_INTERVAL_MILLISECONDS =
            MILLISECONDS_PER_SECOND * DETECTION_INTERVAL_SECONDS;
    private boolean mInProgress;
   
    /*
     * Store the PendingIntent used to send activity recognition events
     * back to the app
     */
    private PendingIntent mActivityRecognitionPendingIntent;
    // Store the current activity recognition client
    private ActivityRecognitionClient mActivityRecognitionClient;
    
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
	     /*
         * Create a new location client, using the enclosing class to
         * handle callbacks.
         */
        mLocationClient = new LocationClient(this, this, this);
        mLocationClient.connect();
        
        map = ((SupportMapFragment)(this.getSupportFragmentManager().findFragmentById(R.id.MyMap))).getMap();
        
        // SET CLASS ON LOCATION Change Listener
        //map.setOnMyLocationChangeListener(this);
        
        // Set map Store Info Window Adapter
        
        addMarker = (Button) this.findViewById(R.id.AddMarker);
        addMarker.setOnClickListener(this);
        
        Button london = (Button) this.findViewById(R.id.ShowMe);
        london.setOnClickListener(this);
        
        Button snapshot = (Button) this.findViewById(R.id.SnapShot);
        snapshot.setOnClickListener(this);
        
        Button locations = (Button) this.findViewById(R.id.LocationDetails);
        locations.setOnClickListener(this);
        
        Button zoomOut = (Button) this.findViewById(R.id.ZoomOut);
        zoomOut.setOnClickListener(this);
        
        geo = new Geocoder(this, Locale.getDefault());
        
        map.setOnMapLongClickListener(this);
        
        map.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
		
        map.setOnCameraChangeListener(this);
        
		map.setOnMarkerClickListener(this);
		
		map.setMyLocationEnabled(true);
		
		map.getUiSettings().setMyLocationButtonEnabled(true);
		
		map.getUiSettings().setZoomControlsEnabled(false);
		
		map.getUiSettings().setCompassEnabled(true);
		
		
		
		
		
	}
	
	@Override
	 protected void onResume() {
	  // TODO Auto-generated method stub
	  super.onResume();

	  int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(getApplicationContext());
	  
	  if (resultCode == ConnectionResult.SUCCESS){

	   Toast.makeText(getApplicationContext(), 
	     "isGooglePlayServicesAvailable SUCCESS", 
	     Toast.LENGTH_LONG).show();
	  }else{
	   GooglePlayServicesUtil.getErrorDialog(resultCode, this, 1);
	  }
	  
	 }

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}
	
	 public void startUpdates() {
	        // Check for Google Play services
		 	
	        if (ConnectionResult.SUCCESS!=GooglePlayServicesUtil.isGooglePlayServicesAvailable(getApplicationContext())) {
	            return;
	        }
	        
	        // If a request is not already underway
	        if (!mInProgress) {
	            // Indicate that a request is in progress
	            mInProgress = true;
	            // Request a connection to Location Services
	            mActivityRecognitionClient.connect();
	        //
	        } else {
	        	
	        	mActivityRecognitionClient.disconnect();
	        	
	        	mInProgress = false;
	        	
	        	
	        	
	            /*
	             * A request is already underway. You can handle
	             * this situation by disconnecting the client,
	             * re-setting the flag, and then re-trying the
	             * request.
	             */
	        }
	    }

	
	
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId())
		{
		case R.id.m_settings:
			Intent intent = new Intent(this, SettingsActivity.class); // Intent starts a Fragment (Should be an Activity)
			intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
			startActivity(intent);
			return true;
		
		default:
			return super.onOptionsItemSelected(item);
		
		
		}
	}

	@Override
	public boolean onMarkerClick(Marker arg0) {
		// TODO Auto-generated method stub
		return false;
	}






	@Override
    public void onDisconnected() {
		
		if((mActivityRecognitionClient.isConnected() == false))
		{
			// Turn off the request flag
			mInProgress = false;
			// Delete the client
			mActivityRecognitionClient = null;
        
			
		}
    }
	
	@Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        // Turn off the request flag
        mInProgress = false;
        /*
         * If the error has a resolution, start a Google Play services
         * activity to resolve it.
         */
        if (connectionResult.hasResolution()) {
            try {
                connectionResult.startResolutionForResult(
                        this,
                        ConnectionResult.NETWORK_ERROR);
            } catch (SendIntentException e) {
                // Log the error
                e.printStackTrace();
            }
        // If no resolution is available, display an error dialog
        } else {
            // Get the error code
            int errorCode = connectionResult.getErrorCode();
            // Get the error dialog from Google Play services
            Dialog errorDialog = GooglePlayServicesUtil.getErrorDialog(
                    errorCode,
                    this,
                    ConnectionResult.NETWORK_ERROR);
            errorDialog.show();
            // If Google Play services can provide an error dialog
            
        }
	}

	@Override
	public void onMyLocationChange(Location arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onConnected(Bundle arg0) {
		
		if(mLocationClient.isConnected())
		{
			
		
		
		Location myLocation = mLocationClient.getLastLocation();
		final LatLng thePos = new LatLng(myLocation.getLatitude(), myLocation.getLongitude());
		float f = new Float(16);
		CameraPosition CamPos = CameraPosition.fromLatLngZoom(thePos, f);
		CameraUpdate update = CameraUpdateFactory.newCameraPosition(CamPos);
		
		map.animateCamera(update);
		
		int strokeColor = 0xffff0000; //red outline
	    int shadeColor = 0x44ff0000; //opaque red fill
		
	    int myposFill = 0x6699FF;
	    int myposStroke = 0x3366FF;
	    
	    
	  
	    
	    
		// Circle your location
		myZone = new CircleOptions()
		.center(thePos)
		.radius(500);
		
		myZone.fillColor(shadeColor);
		myZone.strokeColor(strokeColor);
		myZone.strokeWidth(4);
		
		circle = map.addCircle(myZone);
		
	
		
		  CircleOptions ActualO = new CircleOptions()
			.center(thePos)
			.radius(90);
			
			ActualO.fillColor(myposFill);
			ActualO.strokeColor(myposStroke);
			ActualO.strokeWidth(8);
			
			map.addCircle(ActualO);
		
		
		
		
		
		}
		
		
			if(mActivityRecognitionClient.isConnected())
			{
	        mActivityRecognitionClient.requestActivityUpdates(
	                30000,
	                mActivityRecognitionPendingIntent);
	        Toast.makeText(this, "App is now aware of your activity", 200).show();
	            
	        /*
	         * Since the preceding call is synchronous, turn off the
	         * in progress flag and disconnect the client
	         */
	       // mInProgress = false;
	        //mActivityRecognitionClient.disconnect();
	        
			}
		
	}
	
	public static Bitmap createContrast(Bitmap src, double value) {
	    // image size
	    int width = src.getWidth();
	    int height = src.getHeight();
	    // create output bitmap
	    Bitmap bmOut = Bitmap.createBitmap(width, height, src.getConfig());
	    // color information
	    int A, R, G, B;
	    int pixel;
	    // get contrast value
	    double contrast = Math.pow((100 + value) / 100, 2);
	 
	    // scan through all pixels
	    for(int x = 0; x < width; ++x) {
	        for(int y = 0; y < height; ++y) {
	            // get pixel color
	            pixel = src.getPixel(x, y);
	            A = Color.alpha(pixel);
	            // apply filter contrast for every channel R, G, B
	            R = Color.red(pixel);
	            R = (int)(((((R / 255.0) - 0.5) * contrast) + 0.5) * 255.0);
	            if(R < 0) { R = 0; }
	            else if(R > 255) { R = 255; }
	 
	            G = Color.red(pixel);
	            G = (int)(((((G / 255.0) - 0.5) * contrast) + 0.5) * 255.0);
	            if(G < 0) { G = 0; }
	            else if(G > 255) { G = 255; }
	 
	            B = Color.red(pixel);
	            B = (int)(((((B / 255.0) - 0.5) * contrast) + 0.5) * 255.0);
	            if(B < 0) { B = 0; }
	            else if(B > 255) { B = 255; }
	 
	            // set new pixel color to output bitmap
	            bmOut.setPixel(x, y, Color.argb(A, R, G, B));
	        }
	    }
	 
	    // return final image
	    return bmOut;
	}

	@Override
	public void onMapLongClick(LatLng latlng) {
		// TODO Auto-generated method stub
		
		map.addMarker(new MarkerOptions()
        .position(latlng)
        .title("Test Marker"));
		
		storeMarkerLocs.add(latlng);
		
		
	}

	@Override
	public void onClick(View v) {
		// TODO Auto-generated method stub
		switch(v.getId())
		{
		
		case R.id.AddMarker:
			if(sLine == false)
			{
			
			PolylineOptions lineOptions = new PolylineOptions()
	        .width(5)
		    .color(Color.RED);
			
			for(LatLng ll: storeMarkerLocs)
			{
				lineOptions.add(ll);
			}
			
		
			
			Polyline line = map.addPolyline(lineOptions);
			addMarker.setText("Clear Line");
			sLine = true;
			}
			else
			{
				map.clear();
				addMarker.setText("Add a Polyline");
				sLine = false;
			}
			break;
			
		
		case R.id.ShowMe:
			
			Location myLoc = mLocationClient.getLastLocation();
			final LatLng somePos = new LatLng(myLoc.getLatitude(), myLoc.getLongitude());
			float f1 = new Float(17);
			CameraPosition CamPos = CameraPosition.fromLatLngZoom(somePos, f1);
			CameraUpdate update = CameraUpdateFactory.newCameraPosition(CamPos);
			
			map.animateCamera(update);
			
			break;
		case R.id.ZoomOut:
			
			zoomLevel = map.getCameraPosition().zoom;
			
			Location myLocation = mLocationClient.getLastLocation();
			final LatLng thePos2 = new LatLng(myLocation.getLatitude(), myLocation.getLongitude());
			zoomLevel -= 2;
			if(zoomLevel<3)
			{
				zoomLevel = 3;
				Toast.makeText(this, "Unable to Zoom Out further", 200).show();
			}
			CameraPosition CamPos2 = CameraPosition.fromLatLngZoom(thePos2, zoomLevel);
			CameraUpdate update2 = CameraUpdateFactory.newCameraPosition(CamPos2);
			
			map.animateCamera(update2);
			
			break;
			
		case R.id.SnapShot:
			
			SnapshotReadyCallback CALLBACK = new SnapshotReadyCallback(){
			Bitmap image;
				
				public void onSnapshotReady(Bitmap snapshot) {
					
					image = snapshot;
					
					try
					{
						String filename = "Location";
						
						FileOutputStream out = new FileOutputStream("/mnt/sdcard/DCIM/Camera/"+filename+".png");
						image.compress(Bitmap.CompressFormat.PNG, 100, out);
						
						
						Bitmap[] barr = new Bitmap[5];
						for(int i = 1; i <= 5; i++)
						{
							barr[i-1] = createContrast(snapshot, (i*5));
						
							image = barr[i-1];
						
						out = new FileOutputStream("/mnt/sdcard/DCIM/Camera/"+filename+" " + i +".png");
						
						image.compress(Bitmap.CompressFormat.PNG, 100, out);
						out.close();
						
						
						}
						Toast.makeText(getApplicationContext(), "Snapshots taken", Toast.LENGTH_LONG).show();
					}
					catch(IOException e)
					{
						Toast.makeText(getApplicationContext(), "Error while taking snapshot", Toast.LENGTH_LONG).show();
						Log.e("QMApp", "Snapshot error", e);
					}
					
					
				}
				
			};
			
			map.snapshot(CALLBACK);
			
			break;
		case R.id.LocationDetails:
		
			myLocation = mLocationClient.getLastLocation();
			latitude = myLocation.getLatitude();
			longitude = myLocation.getLongitude();
			String city;
			String message = "Could not get location";
			try {
				city = geo.getFromLocation(latitude, longitude, 1).get(0).getAddressLine(1);
				
				Toast.makeText(getApplicationContext(), 
					     city, 
					     Toast.LENGTH_LONG).show();
			} catch (IOException e) {
							
				Toast.makeText(getApplicationContext(), 
						message, 
					     Toast.LENGTH_LONG).show();
				
				Log.e("QMApp", "Location could not be recived", e);
			}
		
			break;
		default: 
			break;
		
		}
	}

	@Override
	public void onCameraChange(CameraPosition cp) {
		// TODO Auto-generated method stub
		
		//LocationManager lm = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
		
		myLocation = new Location("CamLoc");
		myLocation.setLatitude(cp.target.latitude);
		myLocation.setLongitude(cp.target.longitude);
		
		LatLng aPos = new LatLng(myLocation.getLatitude(),myLocation.getLongitude());
		
		circle.remove();
		
		myZone.center(aPos);
		
		circle = map.addCircle(myZone);

		
	}

}
